package com.example.haojiutao.controller.user;


import com.example.haojiutao.common.Result;
import com.example.haojiutao.constant.CacheKeyConstant;
import com.example.haojiutao.constant.Enum.ExceptionCodeEnum;
import com.example.haojiutao.interceptor.JWTProperties;
import com.example.haojiutao.model.domain.Message;
import com.example.haojiutao.model.domain.Messagelist;
import com.example.haojiutao.model.domain.User;
import com.example.haojiutao.service.UserService;
import com.example.haojiutao.utils.*;
import com.github.pagehelper.PageInfo;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import io.jsonwebtoken.Claims;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.*;

@Slf4j
@RestController("UserController")

/**
 * @Description: 用户控制层
 * @Author: cheng_jianzhen
 * @CreateTime: 2024/1/20 20:31
 */

public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private JWTProperties jwtProperties;
    //获取个人信息
    //@GetMapping("/user/info") //只支持GET请求，如果是POST访问返回405
    /*
     * @Description: 验证码
     * @Author: cheng_jianzhen
     * @CreateTime: 2024/1/20 20:46
     * @param: null
     * @return: null
     **/
    //Redis 注解
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private DefaultKaptcha captchaProducer; //配置自动装配验证码的生成器
    @ResponseBody
    public User gerUserInfo(){
        //初始化用户信息
        User user=new User();


        user.setSex("男");

        user.setUserName("zhangsan");
        user.setPhoneNum("1233");
        user.setIntroduction("只是我的自我介绍");

        return  user;
    }
    /*
     * @Description: 注册用户
     * @Author: cheng_jianzhen
     * @CreateTime: 2024/1/20 20:55
     * @param: user
     * @return: java.lang.String
     **/
    @PostMapping("/user/register") //等于@RequestMapping(method =POST ,value ="/path" )
    public Result register(HttpServletRequest request, @RequestBody User user) {

        log.info("注册用户信息：{}", user);
        //1.校验请求参数是否为空，还需校验手机号，用户名，密码
        String uuid = user.getUuid();
        String smsCode = user.getSmsCode();
        if(!StringUtils.hasLength(uuid) || !StringUtils.hasLength(smsCode)){
            return Result.faile("短信验证码不能为空！");
        }
        //2.校验用户输入短信验证码与服务器短信验证码是否一致；TODO 需要使用 缓存数据库 Redis 保存验证码等信息
        //ServletContext context = request.getServletContext();
        String smsCodeKey = CacheKeyConstant.getSmsCodeRegisterKey(uuid);
        //String serverSmsCode = context.getAttribute("sms_code_register-" + uuid) == null ? "" :context.getAttribute("sms_code_register-" + uuid).toString();
        //String serverSmsCode = context.getAttribute(smsCodeKey) !=null ? context.getAttribute(smsCodeKey).toString(): "";
        String serverSmsCode = redisUtil.get(smsCodeKey) !=null ? redisUtil.get(smsCodeKey).toString(): "";
        if(!serverSmsCode.equals(smsCode)){
            // return Result.faile(100010,"验证码不正确");
            return Result.faile(ExceptionCodeEnum.SMS_VERIFYCODE_ERROR);
        }
        return userService.register(user);
    }
    /*
     * @Description: 用户登录
     * @Author: cheng_jianzhen
     * @CreateTime: 2024/1/20 21:20
     * @return: com.example.treasure_box.common.Result
     **/
    @PostMapping("/user/login")
    public Result login(HttpServletRequest request,@RequestBody User user){
        /* FIXME 打印请求头信息 */
        Iterator<String> iterator = request.getHeaderNames().asIterator();
        while (iterator.hasNext()){
            String header = iterator.next();
            log.info("defaultKaptcha 头信息： {} - {}" ,header, request.getHeader(header));
        }
        /* FIXME 打印请求头信息 */
        /*
       实现思路：
       1.获取请求参数，并进行校验（是否为空校验，图片验证码是否正确）；
       2.校验账号。密码是否正确：根据手机号，密码查询数据库是否存在该记录；
       3.返回登录成功
        */
        log.info("用户登录请求参数：{}",user);
        String phone =user.getPhoneNum();
        String userPwd = user.getUserPwd();
        String verifyCode = user.getVerifyCode();
        String uuid = user.getUuid();
        //1.获取请求参数，并进行校验（是否为空校验，图片验证码是否正确）；
        if(!StringUtils.hasLength(phone)|| !StringUtils.hasLength(userPwd)
                ||!StringUtils.hasLength(verifyCode) ||!StringUtils.hasLength(uuid)){
            log.error("请求参数uuid.phone.verifyCode.password 为空");
            return Result.faile(ExceptionCodeEnum.LOGIN_ERROR_PHONE_PASSWORD_VERIFYCODE_IS_NULL);
        }
        //ServletContext context = request.getServletContext();
        String verifyCodeKey = CacheKeyConstant.getVerifyCodeKey(uuid);//获取图片验证码缓存key
        //系统保存的图片验证码
        //String temVerifyCode = null == context.getAttribute(verifyCodeKey) ?"" : context.getAttribute(verifyCodeKey).toString();
        String temVerifyCode = null == redisUtil.get(verifyCodeKey) ?"" : redisUtil.get(verifyCodeKey).toString();
        if(!temVerifyCode.equals(verifyCode)){
            log.error("用户登录失败：图片验证码错误！系统保存验证码：{}",temVerifyCode);
            return Result.faile(ExceptionCodeEnum.IMAGE_VERIFYCODE_IS_ERROR);
        }

        //2.校验账号。密码是否正确：根据手机号，密码查询数据库是否存在该记录；
        user = userService.login(phone,userPwd);
        if(null == user){
            return Result.faile(ExceptionCodeEnum.ACCOUNT_PASSWORD_ERROR);
        }
        //登录成功：TODO
        //context.setAttribute(CacheKeyConstant.getTokenKey(token),token);
        //context.setAttribute(CacheKeyConstant.getTokenKey(token),user);
//        // 将user保存至服务器
//        redisUtil.set(CacheKeyConstant.getTokenKey(token),user);
        Map<String,Object> claims = new HashMap<>();
        claims.put("user",user);
        String secretKey = jwtProperties.getSecretKey();
        long ttl = jwtProperties.getTtl();
        String token = JwtUtil.createJWT(secretKey, ttl, claims);  //需要使用 JWT 生成
        redisUtil.set(CacheKeyConstant.getTokenKey(token), user);
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        return Result.success("登录成功！",map);
    }
    @PostMapping("/user/parseJWT")
    public Result reParseJWT(@RequestBody String token){
        String secretKey = jwtProperties.getSecretKey();
        System.out.println("前端传过来的token："+token);
        Map<String, Object> claims = JwtUtil.parseJWT(secretKey, token);
        System.out.println("解密后的token："+claims);
        return Result.success("解密成功",claims);
    }

    /*
     * @Description: //为普通用户提供控制器，用户个人信息查案，注册登录
     * @Author: cheng_jianzhen
     * @CreateTime: 2024/1/20 21:49
     * @return: com.example.musicserver.common.Result
     **/
    @RequestMapping(method={RequestMethod.GET,RequestMethod.POST}, value="/user/info")
    /*
     * @Description: TODO 需要从登录对象中获取当前用户ID
     * @Author: cheng_jianzhen
     * @CreateTime: 2024/1/20 21:52
     * @return: com.example.treasure_box.common.Result
     **/
    public Result getUserInfo(){

//        int userId=64;
//        User user=userService.selectById(userId);
        //从当前线程中读取登录用户信息
        User user = H5LoginUserUtil.getLoginUser();
        System.out.println("==========="+ user);
        return Result.success("查询成功",user);
    }


    /*
     * @Description: TODO用户修改个人信息
     * @Author: cheng_jianzhen
     * @CreateTime: 2024/1/20 22:12
     * @param: user
     * @return: com.example.musicserver.common.Result
     **/
    @PutMapping("/user/info")
    public int updateInfo(@RequestBody User user){
        log.info("待修改的个人信息 ：{}" ,user);
//        user.setId(user.getId());
        return userService.updateUser(user);

    }
    /*
     * @Description: TODO添加用户
     * @Author: cheng_jianzhen
     * @CreateTime: 2024/1/20 22:24
     * @param: user
     * @return: com.example.treasure_box.common.Result
     **/
    @PostMapping("/user/user")
    public Result adduser(@RequestBody User user) {

        log.info("联系商家",user);

        return userService.insertuser(user);
    }


    /*
     * @Description: 删除用户
     * @Author: cheng_jianzhen
     * @CreateTime: 2024/1/20 22:36
     * @param: id
     * @return: com.example.secondhand.common.Result
     **/
    @DeleteMapping("/user/")
    public int delete(Integer id){
        return userService.deleteById(id);
    }
    @DeleteMapping("/user/{id}")
    public Result delete1(@PathVariable("id")  Integer id){

//        return userService.deleteById(id);
        int rows = userService.deleteById(id);
        if(rows == 1){
            return Result.success("删除成功");
        }else{
            return Result.faile("删除失败");
        }
    }

    /*
     * @Description: 列表查询
     * @Author: cheng_jianzhen
     * @CreateTime: 2024/1/20 22:50
     * @param: user
     * @return: com.example.secondhand.common.Result
     **/
@CrossOrigin(origins = {"http://localhost:5173"}, allowCredentials = "true")
    @GetMapping("/user")
    public Result list( User user){
        log.info("列表查询参数 ：{}" ,user);
        List<User> users =userService.listByUser(user);
        PageInfo<User> pageInfo=new PageInfo<>(users);
        return Result.success("查询成功",pageInfo);
    }
    /*
     * @Description: 根据用户ID查询用户
     * @Author: cheng_jianzhen
     * @CreateTime: 2024/1/20 22:59
     * @param: id
     * @return: com.example.haojiutao.common.Result
     **/
    @GetMapping("/user/{id}")   // 请求地址：/admin/songlist/1
    public Result detail(@PathVariable("id") Integer id){
        User user = userService.getById(id);
        return Result.success("查询成功", user);
    }
    @CrossOrigin(origins={"http://localhost:5173"}, allowCredentials = "true")
    @GetMapping("/user/avg")
    public Result getRecommendUseravg(){
        User user=new User();
        user.setPageSize(5); //显示6条；
        return Result.success("查询成功！",
                userService.getRecommendUseravg(user));
    }
    /*
     * @Description: TODO
     * @Author: cheng_jianzhen
     * @CreateTime: 2024/1/20 23:09
     * @param: request
     * @param: httpServletResponse
     * @return: com.example.haojiutao.common.Result
     **/
    @CrossOrigin(origins = {"http://localhost:5173"}, allowCredentials = "true")
    @GetMapping("/user/kaptcha")
    public Result defaultKaptcha(HttpServletRequest request, HttpServletResponse httpServletResponse) throws Exception {
        ByteArrayOutputStream imgOutputStream = new ByteArrayOutputStream();
        //ServletContext context = request.getServletContext();
        try {
            String uuid = UUID.randomUUID().toString();
            //生产验证码字符串并保存到session中
            String verifyCode = captchaProducer.createText();
            System.out.println("CommonController.defaultKaptcha 生成的图片验证码 是：" + verifyCode);
            //1、获取应用上下文 context 对象；
            // 2、将图片验证码写入 context 中，供提交表单时验证。 TODO Redis
            // redisUtil.set("verifyCode-" + uuid, verifyCode,RedisUtil.MINUTE_FIVE);
            String verifyCodeKey = CacheKeyConstant.getVerifyCodeKey(uuid);
            //context.setAttribute(verifyCodeKey, verifyCode);
            redisUtil.set(verifyCodeKey, verifyCode);//写入Redis缓存中
            BufferedImage challenge = captchaProducer.createImage(verifyCode);
            //生成验证码图片
            ImageIO.write(challenge, "jpg", imgOutputStream);//将验证码的图片格式输出为jpg
            Map<String, String> map = new HashMap<>();
            map.put("uuid", uuid);
            map.put("img", Base64.getEncoder().encodeToString(imgOutputStream.toByteArray())
            );
            return Result.success("请求成功", map);
        } catch (IllegalArgumentException e) {
            httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
            return Result.faile(9003, "验证码获取失败!");

        }
    }

    @GetMapping("/user/smscode")
    public Result sendSmsCode(HttpServletRequest request,
                              String uuid, String verifyCode, String phone) {
        //1.校验用户请求参数是否为空；
        if (!StringUtils.hasLength(uuid)
                || !StringUtils.hasLength(verifyCode)
                || !StringUtils.hasLength(phone)
        ) {
            return Result.faile("图片验证码，手机号不能为空！");
        }

        //2.校验用户输入的图片验证码与服务器保存的图片验证码是否一致，如果一致，则继续；
        //ServletContext context = request.getServletContext();
        String verifyCodeKey = CacheKeyConstant.getVerifyCodeKey(uuid);
        // String serverVerfiyCode = context.getAttribute("verifyCode-" + uuid).toString();
        //String serverVerfiyCode = context.getAttribute(verifyCodeKey)!=null? context.getAttribute(verifyCodeKey).toString():"";
        Object serverVerifyCodeObj = redisUtil.get(verifyCodeKey);
        if (null == serverVerifyCodeObj || !verifyCode.equals(serverVerifyCodeObj.toString())) {
            redisUtil.del(verifyCodeKey);//从 Redis 删除相应图片验证码
        //if (!verifyCode.equals(serverVerfiyCode)) {
          //  context.removeAttribute(verifyCodeKey);//将服务器保存的图片验证码删除；
            // return Result.faile("图片验证码错误！");
            // return Result.faile("图片验证码错误！");
            return Result.faile(ExceptionCodeEnum.IMAGE_VERIFYCODE_IS_ERROR);
        }
        //3.生成短信验证码
        String smsCode = RandomNumber.generateNumber();
        //4.调用发送短信验证码工具方法，实现短信发送给用户输入的手机号；
        String result = HttpUtils.sendSms(phone, smsCode);
        if (HttpUtils.HTTP_RESPONSE_RESULT_SUCCESS.equals(result)) {
            String smsCodeKey = CacheKeyConstant.getSmsCodeRegisterKey(uuid);
            //context.setAttribute("sms_code_register-" + uuid, smsCode);
            //context.setAttribute(smsCodeKey,smsCode);
            //context.removeAttribute(verifyCodeKey);//将服务器保存的图片验证码删除
            redisUtil.set(smsCodeKey,smsCode,RedisUtil.MINUTE_FIVE);//将短信验证码保存至Redis,过期时间
            redisUtil.del(verifyCodeKey);//将服务器保存的图片验证码删除
            log.info("UUID={} 发送的短信验证码为：{}", uuid, smsCode);
            //5.返回请求状态给用户
            return Result.success("发送成功！");
        }
        return Result.faile("验证码发送失败！");
    }


}
